// Copyright 2023 Stefan Prodan
// SPDX-License-Identifier: Apache-2.0

package v1alpha1

import "strings"

// Annotations defines the schema for Kubernetes object metadata annotations.
#Annotations: {[string & strings.MaxRunes(253)]: string}

// Labels defines the schema for Kubernetes object metadata labels.
#Labels: {[string & strings.MaxRunes(253)]: string & =~"^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$" & strings.MaxRunes(63)}

#StdLabelName:      "app.kubernetes.io/name"
#StdLabelVersion:   "app.kubernetes.io/version"
#StdLabelPartOf:    "app.kubernetes.io/part-of"
#StdLabelManagedBy: "app.kubernetes.io/managed-by"
#StdLabelComponent: "app.kubernetes.io/component"
#StdLabelInstance:  "app.kubernetes.io/instance"

// Metadata defines the schema for Kubernetes object metadata.
#Metadata: {
	// Version should be in the strict semver format. Is required when creating resources.
	#Version!: string & strings.MaxRunes(63)

	// Name must be unique within a namespace. Is required when creating resources.
	// Name is primarily intended for creation idempotence and configuration definition.
	// More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names#names
	name!: #InstanceName

	// Namespace defines the space within which each name must be unique.
	// More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces
	namespace!: #InstanceNamespace

	// Annotations is an unstructured key value map stored with a resource that may be
	// set to store and retrieve arbitrary metadata.
	// More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations
	annotations?: #Annotations

	// Map of string keys and values that can be used to organize and categorize (scope and select) objects.
	// More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels
	labels: #Labels

	// Standard Kubernetes labels: app name, version and managed-by.
	labels: {
		(#StdLabelName):      name
		(#StdLabelVersion):   #Version
		(#StdLabelManagedBy): "timoni"
	}

	// LabelSelector selects Pods based on the app.kubernetes.io/name label.
	#LabelSelector: #Labels & {
		(#StdLabelName): name
	}

	// Finalizers are namespaced keys that tell Kubernetes to wait until specific conditions
	// are met before it fully deletes resources marked for deletion.
	// More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/finalizers/
	finalizers?: [...string]
}

// MetaComponent generates the Kubernetes object metadata for a module namespaced component.
// The metadata.name is composed of the instance name and the component name.
// The metadata.labels contain the app.kubernetes.io/component label.
#MetaComponent: {
	// Meta is the Kubernetes object's metadata generated by Timoni.
	#Meta!: #Metadata

	// Component is the name of the component used
	// as a suffix for the generate object name.
	#Component!: string & strings.MaxRunes(30)

	name:      #Meta.name + "-" + #Component
	namespace: #Meta.namespace

	labels: #Meta.labels
	labels: (#StdLabelComponent): #Component

	annotations?: #Annotations
	if #Meta.annotations != _|_ {
		annotations: #Meta.annotations
	}

	// LabelSelector selects Pods based on the app.kubernetes.io/name
	// and app.kubernetes.io/component labels.
	#LabelSelector: #Labels & {
		(#StdLabelComponent): #Component
		(#StdLabelName):      #Meta.name
	}
}

// MetaClusterComponent generates the Kubernetes object metadata for a module non-namespaced component.
// The metadata.name is composed of the instance name and the component name.
// The metadata.namespace is unset.
// The metadata.labels contain the app.kubernetes.io/component label.
#MetaClusterComponent: {
	// Meta is the Kubernetes object's metadata generated by Timoni.
	#Meta!: #Metadata

	// Component is the name of the component used
	// as a suffix for the generate object name.
	#Component!: string & strings.MaxRunes(30)

	name: #Meta.name + "-" + #Component

	labels: #Meta.labels
	labels: (#StdLabelComponent): #Component

	annotations?: #Annotations
	if #Meta.annotations != _|_ {
		annotations: #Meta.annotations
	}

	// LabelSelector selects Pods based on the app.kubernetes.io/name
	// and app.kubernetes.io/component labels.
	#LabelSelector: #Labels & {
		(#StdLabelComponent): #Component
		(#StdLabelName):      #Meta.name
	}
}
